package com.wmd.core.util;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * 类说明
 * 
 * @author yincheng lu
 * @time 2019年1月11日下午4:19:28
 * @Description
 */
public class BeanUtils {
	public static boolean isNull(Object o,String[] excluse) {
		if(o==null) {
			return true;
		}
		Field[] fields=o.getClass().getDeclaredFields();
		Set<String> excluseSet=new HashSet<String>(Arrays.asList(excluse));
		for(int i=0;i<fields.length;i++) {
			if("serialVersionUID".equals(fields[i].getName())){
				continue;
			}
			if(excluseSet.contains(fields[i].getName())) {
				continue;
			}else {
				try {
					fields[i].setAccessible(true);
					if(fields[i].get(o)!=null) {
						return false;
					}
				} catch (IllegalArgumentException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return true;
	}
	public static <T> T getBeanFromMap(Map source, T t) {
		try {
			Field[] t_field = t.getClass().getDeclaredFields();
			for (Field f : t_field) {
				String fieldName = f.getName();
				if("serialVersionUID".equals(fieldName)){
					continue;
				}
				f.setAccessible(true);
				Object sourceFieldValue = source.get(fieldName);
				if (sourceFieldValue == null) {
					continue;
				}
				try {
					Class<?> f_type=f.getType();
					if (sourceFieldValue instanceof BigDecimal && f_type.equals(Integer.class)) {
						f.set(t, Integer.parseInt(((BigDecimal) sourceFieldValue).toString()));
					}else if(f_type.equals(Date.class)){
						if(sourceFieldValue instanceof Long){
							f.set(t,new Date((Long) sourceFieldValue));
						}else if(sourceFieldValue instanceof Date){
							f.set(t,sourceFieldValue);
						}else{
							f.set(t,sourceFieldValue);
						}
					}else if(f_type.equals(Long.class)){
						f.set(t,Long.parseLong(sourceFieldValue+""));
					}
					else {
						f.set(t, sourceFieldValue);
					}
				} catch (SecurityException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					continue;
				}
			}
			return t;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static <T> T getBeanFromMap(Map source, Class<?> result) {
		try {
			T t = (T) result.newInstance();
			return getBeanFromMap(source,t);
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static <T> T getBeanFromBenaAll(Object source, Class<T> result) {
		try {
			T t = result.newInstance();
			Class<?> currentClass = result;
			List<Field> fields = new ArrayList<>();
			while (currentClass != null) {
				final Field[] declaredFields = currentClass.getDeclaredFields();
				for (final Field field : declaredFields) {
					fields.add(field);
				}
				currentClass = currentClass.getSuperclass();
			}
//			Field[] t_field = result.getDeclaredFields();
			Class<?> sourceClass=source.getClass();
			for (Field f : fields) {
				String fieldName = f.getName();
				f.setAccessible(true);
				if("serialVersionUID".equals(fieldName)){
					continue;
				}
				try {
					Field source_field = sourceClass.getDeclaredField(fieldName);
					if(source_field==null){
						continue;
					}
					source_field.setAccessible(true);
					Object o=source_field.get(source);
					if(o==null){
						continue;
					}
					if (f.getType().equals(String.class)) {
						f.set(t, o + "");
					} else if (f.getType().equals(Integer.class)) {
						f.set(t, Integer.parseInt(o + ""));
					} else {
						f.set(t, o);
					}
				} catch (NoSuchFieldException | SecurityException e) {
					// TODO Auto-generated catch block
					System.out.println("not such field or security exception");
					continue;
				}
			}
			return t;
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}
	public static void getBeanFromBenaDeclared(Object source, Object t) {
		try {
			Field[] t_field = t.getClass().getDeclaredFields();
			for (Field f : t_field) {
				String fieldName = f.getName();
				if("serialVersionUID".equals(fieldName)){
					continue;
				}
				f.setAccessible(true);
				try {
					Field source_field = source.getClass().getDeclaredField(fieldName);
					source_field.setAccessible(true);
					Object o=source_field.get(source);
					if(o==null){
						continue;
					}
					if(StringUtil.isEmpty(o)){
						continue;
					}
					if (f.getType().equals(String.class)) {
						f.set(t, o + "");
					} else if (f.getType().equals(Integer.class)) {
						f.set(t, Integer.parseInt(o + ""));
					} else {
						f.set(t, o);
					}
				} catch (NoSuchFieldException | SecurityException e) {
					// TODO Auto-generated catch block
					System.out.println("not such field or security exception");
					continue;
				}
			}
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
		public static <T> T getBeanFromBenaDeclared(Object source, Class<T> result) {
		try {
			T t = result.newInstance();
			Field[] t_field = result.getDeclaredFields();
			for (Field f : t_field) {
				String fieldName = f.getName();
				if("serialVersionUID".equals(fieldName)){
					continue;
				}
				f.setAccessible(true);
				try {
					Field source_field = source.getClass().getDeclaredField(fieldName);
					source_field.setAccessible(true);
					Object o=source_field.get(source);
					if(o==null){
						continue;
					}
					if (f.getType().equals(String.class)) {
						f.set(t, o + "");
					} else if (f.getType().equals(Integer.class)) {
						f.set(t, Integer.parseInt(o + ""));
					} else {
						f.set(t, o);
					}
				} catch (NoSuchFieldException | SecurityException e) {
					// TODO Auto-generated catch block
					System.out.println("not such field or security exception");
					continue;
				}
			}
			return t;
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	public static Map<String, Object> getMapFromBean(Object bean) {
		Map<String, Object> map = new HashMap<String, Object>();
		Field[] fields = bean.getClass().getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			if("serialVersionUID".equals(fields[i].getName())){
				continue;
			}
			fields[i].setAccessible(true);
			try {
				Object o = fields[i].get(bean);
				// if (o != null) {
				map.put(fields[i].getName(), o);
				// }
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return map;
	}

	public static Map<String, Object> getMapFromBeanAll(Object bean) {
		Map<String, Object> map = new HashMap<String, Object>();
		List<Field> fields = new ArrayList<>();
		Class<?> currentClass = bean.getClass();
		while (currentClass != null) {
			final Field[] declaredFields = currentClass.getDeclaredFields();
			for (final Field field : declaredFields) {
				fields.add(field);
			}
			currentClass = currentClass.getSuperclass();
		}
		for (int i = 0; i < fields.size(); i++) {
			if("serialVersionUID".equals(fields.get(i).getName())){
				continue;
			}
			fields.get(i).setAccessible(true);
			try {
				Object o = fields.get(i).get(bean);
				// if (o != null) {
				map.put(fields.get(i).getName(), o);
				// }
			} catch (IllegalArgumentException | IllegalAccessException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return map;
	}

	public static List<Map<String, Object>> getMapFromList(List<? extends Object> beas) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		beas.forEach(b -> {
			list.add(getMapFromBean(b));
		});
		return list;
	}

	public static Map<String, Object> getMapFromBeans(Object... beans) {
		Map<String, Object> map = new HashMap<String, Object>();
		for (int i = 0; i < beans.length; i++) {
			Field[] fields = beans[i].getClass().getDeclaredFields();
			for (int j = 0; j < fields.length; j++) {
				fields[j].setAccessible(true);
				try {
					Object o = fields[j].get(beans[i]);
					if (o != null) {
						map.put(fields[j].getName(), o);
					}
				} catch (IllegalArgumentException | IllegalAccessException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		return map;
	}

	public static <T> void fitBeanAll(T bean) throws IllegalArgumentException, IllegalAccessException {

		List<Field> fields = new ArrayList<>();
		Class<?> currentClass = bean.getClass();
		while (currentClass != null) {
			final Field[] declaredFields = currentClass.getDeclaredFields();
			for (final Field field : declaredFields) {
				fields.add(field);
			}
			currentClass = currentClass.getSuperclass();
		}
		System.out.println(fields.size());
		Random random = new Random(8);
		for (int i = 0; i < fields.size(); i++) {
			fields.get(i).setAccessible(true);
			Class<?> fieldClass = fields.get(i).getType();
			Object value;
			if (fieldClass.equals(String.class)) {
				value = getRandomString(random.nextInt(10)+1);
			} else if (fieldClass.equals(Integer.class)) {
				value = random.nextInt(9)+1;
			} else if (fieldClass.equals(Long.class)) {
				value = Long.parseLong(random.nextInt(9)+1+"");
			} else if (fieldClass.equals(Date.class)) {
				value = new Date();
			} else if (fieldClass.equals(BigDecimal.class)) {
				value = new BigDecimal(random.nextInt(9)+1);
			} else {
				value = "";
			}
			fields.get(i).set(bean, value);

		}
		// return bean;
	}

	public static <T> Object fitBeanMethod(T bean, String methodName, Class<?>[] classes, Object[] params)
			throws IllegalArgumentException, IllegalAccessException {

		Method method;

		try {
			method = bean.getClass().getMethod(methodName, classes);
			return method.invoke(bean, params);
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// return bean;
		catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public static String getRandomString(int length) {
		System.out.println(length);
		String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(62);
			sb.append(str.charAt(number));
		}
		return sb.toString();
	}
}
